package org.dfl.core.data.connectors;

import org.dfl.core.data.types.TypeContainer;

/**
 * Type connectors are used to connect 2 type containers and recompute their types.
 * @author Piotr Wlodarczyk
 *
 */
public abstract class TypeConnector {
	protected TypeContainer topTypeContainer1;
	protected TypeContainer topTypeContainer2;

	/**
	 * create a type connector for 2 type containers
	 * @param typeContainer1 - first top type container 
	 * @param typeContainer2 - second top type container 
	 */
	public TypeConnector(TypeContainer typeContainer1, TypeContainer typeContainer2) {
		super();
		this.topTypeContainer1 = typeContainer1;
		this.topTypeContainer2 = typeContainer2;
	}

	/**
	 * return source type container This can be a subtype container 
	 * of a first type container e.g. in a map.
	 * @return source TypeContainer
	 */
	protected abstract TypeContainer getSource();

	/**
	 * return target type container. This can be a subtype container 
	 * of a second type container e.g. in a map.
	 * @return target TypeContainer
	 */
	protected abstract TypeContainer getTarget();
	
	/**
	 * Return TypeContainer connected with one passed as an argument by this connector 
	 * @param t	one of connection TypeContainer's
	 * @return second TypeContainer 
	 */
	public TypeContainer getSecondTopTypeContainer(TypeContainer t){
		if(t == topTypeContainer1){
			return topTypeContainer2;
		}else if(t == topTypeContainer2){
			return topTypeContainer1;
		}else{
			return null;
		}
	}
	
	/**
	 * "Executes" the connector - connects first and second TypeContainer 
	 * @return true when no errors occured
	 */
	public boolean connect(){
		if(reconnect()){
			topTypeContainer1.addNeighbour(this);
			topTypeContainer2.addNeighbour(this);
			return true;
		}else{
			return false;
		}
	}
	/**
	 * change type container (change connection)
	 * @param oldC
	 * @param newC
	 */
	public void changeTypeContainer(TypeContainer oldC, TypeContainer newC){
		if(topTypeContainer1 == oldC){
			this.topTypeContainer1 = newC;
		}else if(topTypeContainer2 == oldC){
			this.topTypeContainer2 = newC;
		}
	}

	/**
	 * reconnect
	 * @return true when no errors ocured
	 */
	public boolean reconnect() {
		return getSource().getType().merge(getTarget().getType());
	}
}
